package model.impl;

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import model.EMenuState;
import model.IControllerModel;
import model.INetworkModel;
import model.IViewModel;
import model.IinGame;
import model.impl.menu.IMainMenu;

import controller.impl.KeyPress;

import sharedGameLogic.enums.BattleEvent;
import sharedGameLogic.gameData.BattleResult;
import sharedGameLogic.gameData.InitialStatus;
import sharedGameLogic.gameData.PlayerResult;
import sharedGameLogic.players.Character;
import sharedGameLogic.players.Player;
import sharedNetwork.Connection;
import sharedNetwork.NetworkFlags;


public class Model implements StateListener, INetworkModel, IViewModel, IControllerModel {
	private static final Model INSTANCE = new Model();
	private IModelState currentState = null;
	private List<IModelListener> listeners;
	private List<ModelListener> modelListeners;
	private Queue<Object> dataToSend;
	private Connection connection;
	private Character selectedCharacter;
	private int delta;
	private String serverAdress;
	private String nickName;
	private boolean fullScreen;
	
	private Model() {
		listeners = new LinkedList<IModelListener>();
		modelListeners = new LinkedList<ModelListener>();
		dataToSend = new LinkedList<Object>();
		serverAdress = "127.0.0.1";
		nickName = "Player";
		fullScreen = false;
	}
	
	
	static Model getInstance() {
		return INSTANCE;
	}
	
	public static INetworkModel getNetworkModel() {
		return INSTANCE;
	}
	
	public static IViewModel getViewModel() {
		return INSTANCE;
	}
	
	public static IControllerModel getControllerModel() {
		return INSTANCE;
	}
	
	@Override
	public Object getData() {
		return dataToSend.poll();
	}
	
	@Override
	public Connection getConnection() {
		return connection;
	}
	
	@Override
	public void addModelListener(ModelListener listener) {
		modelListeners.add(listener);
	}
	
	@Override
	public void init() {
		currentState = MenuState.getInstance();
		currentState.addStateListener(this);
	}
	
	@Override
	public void newInput(KeyPress keyPress, int delta) {
		this.delta = delta;
		currentState.newInput(keyPress);
	}
	
	@Override
	public void newData(Object obj, int delta) {
		this.delta = delta;
		if (obj instanceof BattleResult) {
			BattleResult result = (BattleResult) obj;
			PlayerResult player1 = result.getFirstPlayer();
			PlayerResult player2 = result.getSecondPlayer();
			System.out.println("Player1 hp: " + player1.getNewHealth() 
								+ "\nPlayer1 energy: " + player1.getNewEnergy()
								+ "\nPlayer1 action: " + player1.getActionType().toString()
								+ "\n\nPlayer2 hp: " + player2.getNewHealth()
								+ "\nPlayer2 energy: " + player2.getNewEnergy()
								+ "\nPlayer2 action: " + player2.getActionType().toString()
								+ "\n");
			if (player1.getActionType() == BattleEvent.BATTLE_START) {
				currentState.startGame();
			}
		}
		if (obj instanceof InitialStatus) {
			currentState.startGame();
		}
		
		currentState.newData(obj);
	}
	
	@Override
	public void addIModelListener(IModelListener listener) {
		listeners.add(listener);
	}

	@Override
	public void quit() {
		for (IModelListener listener : listeners) {
			listener.exit();
		}
	}

	@Override
	public void viewCharacterSelection() {
		currentState.viewCharacterSelection();
	}

	@Override
	public void viewSettings() {
		currentState.viewSettings();
	}
	
	@Override
	public void viewMainMenu() {
		currentState.viewMainMenu();
	}
	
	@Override
	public IMainMenu getMenuState() {
		return MenuState.getInstance();
	}
	
	@Override
	public IinGame getInGameState() {
		return InGameState.getInstance();
	}
	
	@Override
	public EMenuState getEMenuState() {
		return currentState.getEMenuState();
	}

	@Override
	public void setFullScreen(boolean fullScreen) {
		this.fullScreen = fullScreen;
	}

	@Override
	public void viewConnecting() {
		currentState.viewConnecting();
	}

	@Override
	public void viewInGame() {
		currentState = InGameState.getInstance();
	}

	@Override
	public void startGame() {
		Player player = new Player(nickName, selectedCharacter);
		connection = new Connection(player);
		viewInGame();
		changed();
	}
	
	private void changed() {
		for (ModelListener listener : modelListeners) {
			listener.modelChanged();
		}
	}

	@Override
	public void selectedCharacterChanged(Character selectedCharacter) {
		this.selectedCharacter = selectedCharacter;
	}
	
	public void newObject(Object obj) {
		dataToSend.add(obj);
		changed();
	}
	
	@Override
	public int getDelta() {
		return delta;
	}
	
	@Override
	public boolean isFullScreen() {
		return fullScreen;
	}

	@Override
	public void nickNameChanged(String newNickName) {
		nickName = newNickName;
	}

	@Override
	public void serverAddressChanged(String newAddress) {
		serverAdress = newAddress;
	}
	
	@Override
	public String getServerAddress() {
		return serverAdress;
	}
	
	public void gameFinished() {
		currentState.reset();
		currentState = MenuState.getInstance();
		currentState.reset();
		viewMainMenu();
		dataToSend.add(NetworkFlags.DISCONNECT);
		changed();
	}
}